﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Hive.Core.Common.Shell;

namespace Hive.Core.Model
{
    /// <summary>
    /// A package branch is a container for a particular version of a package.
    /// </summary>
    /// <remarks>
    /// <para>
    /// A package consists of 3 directories.  The contents directory contains a checked
    /// out working copy from a repository.  The imports directory contains files copied
    /// from other projects.  The exports directory contains files that made available
    /// to other projects.
    /// </para>
    /// </remarks>
    public interface IPackageBranch
    {
        /// <summary>
        /// Gets the hive to which this branch belongs.
        /// </summary>
        IHive Hive { get; }

        /// <summary>
        /// Gets the package to which this branch belongs.
        /// </summary>
        IPackage Package { get; }

        /// <summary>
        /// Gets the name of the branch.
        /// </summary>
        string Name { get; }

        /// <summary>
        /// Gets the branch directory.
        /// </summary>
        DirectoryInfo Directory { get; }

        /// <summary>
        /// Gets the contents directory of the branch.
        /// </summary>
        DirectoryInfo GetContentsDirectory();

        /// <summary>
        /// Gets the imports directory of the branch.
        /// </summary>
        DirectoryInfo GetImportsDirectory();

        /// <summary>
        /// Gets the exports directory of the branch.
        /// </summary>
        DirectoryInfo GetExportsDirectory();

        /// <summary>
        /// Returns true if the package branch is in the hive.
        /// </summary>
        /// <exception cref="HiveException">Thrown if the operation failed.</exception>
        bool IsPresent();

        /// <summary>
        /// Gets whether the package branch is currently being used as a source
        /// package, or false if it is being used as a binary branch.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This flag is changed automatically depending on whether <see cref="GetSource" /> or
        /// <see cref="GetBinary"/> was most recently used.
        /// </para>
        /// </remarks>
        /// <exception cref="HiveException">Thrown if the operation failed.</exception>
        bool IsUsingSource();

        /// <summary>
        /// Sets whether the package branch is currently being used as a source
        /// package, or false if it is being used as a binary branch.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This flag is changed automatically depending on whether <see cref="GetSource" /> or
        /// <see cref="GetBinary"/> was most recently used.
        /// </para>
        /// </remarks>
        /// <exception cref="HiveException">Thrown if the operation failed.</exception>
        void SetUsingSource(bool value);

        /// <summary>
        /// Gets the source for this package branch from the source repository.
        /// </summary>
        /// <param name="shell">The shell.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="shell"/> is null.</exception>
        /// <exception cref="HiveException">Thrown if the operation failed.</exception>
        void GetSource(IShell shell);

        /// <summary>
        /// Gets the binary for this package branch from the binary repository.
        /// </summary>
        /// <param name="versionLabel">The version label of the build to get, or null to get the latest.</param>
        /// <param name="shell">The shell.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="shell"/> is null.</exception>
        /// <exception cref="HiveException">Thrown if the operation failed.</exception>
        void GetBinary(string versionLabel, IShell shell);

        /// <summary>
        /// Builds this package branch.
        /// </summary>
        /// <param name="shell">The shell.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="shell"/> is null.</exception>
        /// <exception cref="HiveException">Thrown if the operation failed.</exception>
        void Build(IShell shell);

        /// <summary>
        /// Gets the dependencies of this package branch.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method will return an empty list if the package is not working from source.
        /// </para>
        /// </remarks>
        /// <returns>The list of package branch dependencies.</returns>
        /// <exception cref="HiveException">Thrown if the operation failed.</exception>
        IList<IPackageBranch> GetDependencies();
    }
}
